/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import Cookie from './Cookie.js'
import Log from '../utils/log';
import {CookiePolicy} from './CookieUtils';

var cookie_str_splitter = /[:](?=\s*[a-zA-Z0-9_\-]+\s*[=])/g;

function CookieJar() {
    var  cookies_list, collidable_cookie,cookies,cookiemap,cookieStore;
    this.cookieStore =null;
    this.cookies = Object.create(null);
    return this;
}
CookieJar.prototype.setCookieStore = function setCookieStore(cookieStore) {
    this.cookieStore=cookieStore;
}
CookieJar.prototype.setCookie = function setCookie(cookie, request_domain, request_path) {
    var remove, i;
    Log.showInfo("okhttp- cookiejar setCookie: "+cookie);
    cookie = new Cookie(cookie, request_domain, request_path);
    //Delete the cookie if the set is past the current time
    remove = cookie.expiration_date <= Date.now();
    Log.showInfo("okhttp- cookiejar expiry: "+remove);

    if (this.cookies[cookie.name] !== undefined) {
        Log.showInfo("okhttp- cookiejar cookie present: "+cookie.name);

        this.cookies_list = this.cookies[cookie.name];
        for (i = 0; i < this.cookies_list.length; i += 1) {

            this.collidable_cookie = this.cookies_list[i];
            Log.showInfo("okhttp- cookiejar cookie chcking: "+this.collidable_cookie.name);
            if (this.collidable_cookie.collidesWith(cookie)) {
                if (remove) {
                    Log.showInfo("okhttp- cookiejar cookie removing: "+this.collidable_cookie.name);
                    this.cookies_list.splice(i, 1);
                    if (this.cookies_list.length === 0) {
                        delete this.cookies[cookie.name];
                    }
                    return false;
                }
                Log.showInfo("okhttp- cookiejar cookie adding: "+cookie.name);
                this.cookies_list[i] = cookie;
                return cookie;
            }
        }
        if (remove) {
            return false;
        }
        this.cookies_list.push(cookie);
        return cookie;
    }
    if (remove) {
        return false;
    }
    this.cookies[cookie.name] = [cookie];
    return this.cookies[cookie.name];
};

//returns a cookie
CookieJar.prototype.getCookie = function getCookie(cookie_name, access_info) {
    Log.showInfo("okhttp- getCookie");
    var cookie, i;
    this.cookies_list = this.cookies[cookie_name];
    if (!this.cookies_list) {
        Log.showInfo("okhttp- cookiejar getCookie nocookie: "+cookie_name);
        return;
    }
    for (i = 0; i < this.cookies_list.length; i += 1) {
        cookie = this.cookies_list[i];
        if (cookie.expiration_date <= Date.now()) {
            if (this.cookies_list.length === 0) {
                delete this.cookies[cookie.name];
            }
            continue;
        }
        if(access_info == undefined ){
            return cookie;
        }
        if (cookie.matches(access_info)) {
            Log.showInfo("okhttp- cookiejar matched cookie: "+cookie.name);
            return cookie;
        }
        Log.showInfo("okhttp- cookiejar NO matched cookie: "+cookie_name);
    }
}
//returns a list of cookies
CookieJar.prototype.getCookies = function getCookies(access_info) {
    var matches = [];
    var  cookie_name, cookie;
    /*this.matches.toString = function () {
        return this.join(":");
    };
    this.matches.prototype.toValueString = function () {
        return this.map(function(c) {
            return c.toValueString();
        }).join('; ');
    };
*/
    Log.showInfo("okhttp- cookiejar getCookie checking cookies: ");
    for (cookie_name in this.cookies) {
        cookie = this.getCookie(cookie_name, access_info);
        if (cookie) {
            matches.push(cookie);
        }
    }
    return matches;
}
CookieJar.prototype.saveFromResponse = function saveFromResponse(resp,url,cookiemanager) {
    var cookiePolicy = CookiePolicy.ACCEPT_ORIGINAL_SERVER;
    Log.showInfo("okhttp- cookiemanager: " + cookiemanager.toString());
    if(cookiemanager){
        cookiePolicy= cookiemanager.cookiePolicy;
    }
    Log.showInfo("okhttp- checking cookie policy: "+cookiePolicy);
    if(cookiePolicy === CookiePolicy.ACCEPT_NONE)
            return;
    this.loadForRequest(url);
    var header = resp.header;
    console.log("okhttp- cookie: header " + header);


    Log.showInfo("okhttp- header: " + JSON.stringify(header));

    var responseJSON = JSON.parse(JSON.stringify(header));
    console.log("okhttp- cookie: " + responseJSON["Set-Cookie"]);
    Log.showInfo("okhttp- cookie: " + responseJSON["Set-Cookie"]);

   // var responseJSON = JSON.parse(header.toString());
    if(responseJSON['Set-Cookie']) {
        for (let i = 0; i < responseJSON['Set-Cookie'].length; i += 1) {
            if(cookiePolicy === CookiePolicy.ACCEPT_ORIGINAL_SERVER){
                    if(!this.domainMatches(responseJSON['Set-Cookie'][i],this.extractHostname(url))){
                        Log.showInfo("okhttp- cookie: the cookie domain are not matching");
                        continue;
                    }
            }
            this.setCookie(responseJSON['Set-Cookie'][i]);
        }
        this.saveCookie(url);
    }
}
CookieJar.prototype.loadForRequest = function loadForRequest(url) {
    this.cookies = Object.create(null);
    this.loadCookie(url);
    var cookieHeader = '';
    for (let cookie_name in this.cookies) {
        var cookie = this.getCookie(cookie_name);
        if(cookieHeader.length >0)
        cookieHeader = cookieHeader +';';
        cookieHeader = cookieHeader +cookie.name + "=" + cookie.value;
    }
    Log.showInfo("okhttp- cookieHeader: " +cookieHeader);
    return cookieHeader;
}
CookieJar.prototype.saveCookie =  function saveCookie(url) {
    url = this.extractHostname(url);
    Log.showInfo("okhttp- saveCookie:"+url);
    if (this.cookieStore){
        this.cookieStore.writeCookie(url,JSON.stringify(this.cookies));
    }
    else {
        Log.showInfo("okhttp- loadCookie : not a persistent cookiestore");
    }
    Log.showInfo("okhttp- saveCookie completed:");

}
CookieJar.prototype.loadCookie = function loadCookie(url) {
    url = this.extractHostname(url);
    Log.showInfo("okhttp- loadCookie :"+url);
    if (this.cookieStore) {
        let cookieJSON = this.cookieStore.readCookie(url);
        Log.showInfo("okhttp- loadCookie JSON :"+cookieJSON);
        if(cookieJSON){
            let json= JSON.parse(cookieJSON);
            for (let cookie_name in json) {
                Log.showInfo(JSON.stringify(json[cookie_name]));
                for (var key in json[cookie_name]) {
                    Log.showInfo("okhttp- "+JSON.stringify(json[cookie_name][key]));
                    //console.log(json[cookie_name][key]);
                    let cookiejson = json[cookie_name][key];
                    let cookiestr = [cookiejson.name + "=" + cookiejson.value];
                    if(cookiejson.expiration_date) {
                        if (cookiejson.expiration_date !== Infinity) {
                            cookiestr.push(
                                "expires=" + new Date(cookiejson.expiration_date).toUTCString()
                            );
                        }
                    }
                    if (cookiejson.domain) {
                        cookiestr.push("domain=" + this.domain);
                    }
                    if (cookiejson.path) {
                        cookiestr.push("path=" + cookiejson.path);
                    }
                    if (cookiejson.secure) {
                        cookiestr.push("secure");
                    }
                    if (cookiejson.noscript) {
                        cookiestr.push("httponly");
                    }
                    Log.showInfo("okhttp- cookiestr:"+ cookiestr.join("; "));
                    this.setCookie( cookiestr.join("; "));
                }
            }
        }
    }
    else {
        Log.showInfo("okhttp- loadCookie : not a persistent cookiestore");
    }
}

//returns list of cookies that were set correctly. Cookies that are expired and removed are not returned.
CookieJar.prototype.setCookies = function setCookies(cookies, request_domain, request_path) {
    cookies = Array.isArray(cookies) ?
        cookies :
    cookies.split(cookie_str_splitter);
    var successful = [],
        i,
        cookie;
    cookies = cookies.map(function(item) {
        return new Cookie(item, request_domain, request_path);
    });
    for (i = 0; i < cookies.length; i += 1) {
        cookie = cookies[i];
        if (this.setCookie(cookie, request_domain, request_path)) {
            successful.push(cookie);
        }
    }
    return successful;
};
CookieJar.prototype.extractHostname = function extractHostname(url) {
    var hostname;
    //find & remove protocol (http, ftp, etc.) and get hostname
    if (url.indexOf("//") > -1) {
        hostname = url.split('/')[2];
    }
    else {
        hostname = url.split('/')[0];
    }
    //find & remove port number
    hostname = hostname.split(':')[0];
    //find & remove "?"
    hostname = hostname.split('?')[0];
    return hostname;
}
CookieJar.prototype.domainMatches = function domainMatches(cookie, host) {

    var cookie = new Cookie(cookie);
    var domain =  cookie.domain;
    if(!domain){
        Log.showInfo("okhttp- cookie: the cookie domain is not present");
        return false;
    }
    //Delete the cookie if the set is past the current time

    if (domain == null || host == null) return false;
    Log.showInfo("okhttp- domain:" + domain + "," + "host:" + host);
    // if there's no embedded dot in domain and domain is not .local
    var isLocalDomain = ".local".toLowerCase() === domain.toLowerCase();
    var embeddedDotInDomain = domain.indexOf(".");
    if (embeddedDotInDomain == 0) embeddedDotInDomain = domain.indexOf(".", 1);
    Log.showInfo("okhttp- "+
        "isLocalDomain:" +
        isLocalDomain +
        ",embeddedDotInDomain:" +
        embeddedDotInDomain
    );
    if (
    !isLocalDomain &&
    (embeddedDotInDomain == -1 || embeddedDotInDomain == domain.length - 1)
    )
    return false;
    Log.showInfo("okhttp- "+isLocalDomain + "," + embeddedDotInDomain);
    // if the host name contains no dot and the domain name
    // is .local or host.local
    var firstDotInHost = host.indexOf(".");
    if (
    firstDotInHost == -1 &&
    (isLocalDomain || domain.toLowerCase() === (host + ".local").toLowerCase())
    ) {
        return true;
    }

    var domainLength = domain.length;
    var lengthDiff = host.length - domainLength;
    if (lengthDiff == 0) {
        // if the host name and the domain name are just string-compare euqal
        return host.toLowerCase() === domain.toLowerCase();
    } else if (lengthDiff > 0) {
        // need to check H & D component
        var H = host.substring(0, lengthDiff);
        var D = host.substring(lengthDiff);
        return H.indexOf(".") == -1 && D.toLowerCase() === domain.toLowerCase();
    } else if (lengthDiff == -1) {
        // if domain is actually .host
        return (
            domain.charAt(0) == "." &&
            host.toLowerCase() === domain.substring(1).toLowerCase()
        );
    }

    return false;
}
export default CookieJar;